<?php

namespace App\Services;

use App\Models\Coupon;
use App\Models\UserCoupon;
use App\Models\CouponDistribution;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 优惠券服务类
 *
 * 负责处理优惠券相关的所有业务逻辑
 */
class CouponService
{
    /**
     * 用户领取优惠券
     *
     * @param int $userId
     * @param int $couponId
     * @return array ['success' => bool, 'message' => string, 'user_coupon' => UserCoupon|null]
     */
    public function receive(int $userId, int $couponId): array
    {
        try {
            $coupon = Coupon::find($couponId);

            if (!$coupon) {
                return ['success' => false, 'message' => '优惠券不存在', 'user_coupon' => null];
            }

            // 检查是否可以领取
            $checkResult = $coupon->canUserReceive($userId);
            if (!$checkResult['can_receive']) {
                return ['success' => false, 'message' => $checkResult['reason'], 'user_coupon' => null];
            }

            // 使用事务创建用户优惠券
            $userCoupon = DB::transaction(function () use ($coupon, $userId) {
                // 计算过期时间
                $expireAt = $this->calculateExpireTime($coupon);

                // 创建用户优惠券
                $userCoupon = UserCoupon::create([
                    'user_id' => $userId,
                    'coupon_id' => $coupon->id,
                    'code' => UserCoupon::generateUniqueCode(),
                    'status' => UserCoupon::STATUS_UNUSED,
                    'received_at' => Carbon::now(),
                    'expire_at' => $expireAt,
                ]);

                return $userCoupon;
            });

            return [
                'success' => true,
                'message' => '领取成功',
                'user_coupon' => $userCoupon->load('coupon')
            ];
        } catch (\Exception $e) {
            Log::error('领取优惠券失败', [
                'user_id' => $userId,
                'coupon_id' => $couponId,
                'error' => $e->getMessage()
            ]);

            return ['success' => false, 'message' => '领取失败，请稍后重试', 'user_coupon' => null];
        }
    }

    /**
     * 批量发放优惠券
     *
     * @param int $couponId
     * @param array $userIds
     * @param int $createdBy
     * @param string|null $notes
     * @return array ['success' => bool, 'message' => string, 'distributed_count' => int]
     */
    public function batchDistribute(int $couponId, array $userIds, int $createdBy, ?string $notes = null, int $quantityPerUser = 1): array
    {
        try {
            $coupon = Coupon::find($couponId);

            if (!$coupon) {
                return ['success' => false, 'message' => '优惠券不存在', 'distributed_count' => 0];
            }

            $distributedCount = 0;
            $failedUsers = [];
            $reasons = [];

            DB::transaction(function () use ($coupon, $userIds, $createdBy, $notes, $quantityPerUser, &$distributedCount, &$failedUsers, &$reasons) {
                // 创建分发记录
                $distribution = CouponDistribution::create([
                    'coupon_id' => $coupon->id,
                    'distribution_type' => CouponDistribution::TYPE_MANUAL,
                    'target_users' => $userIds,
                    'quantity' => count($userIds) * $quantityPerUser,
                    'distributed_quantity' => 0,
                    'notes' => $notes,
                    'created_by' => $createdBy,
                ]);

                // 计算过期时间
                $expireAt = $this->calculateExpireTime($coupon);

                // 为每个用户创建优惠券
                foreach ($userIds as $userId) {
                    $user = User::find($userId);
                    if (!$user) {
                        $failedUsers[] = "用户ID: {$userId}";
                        $reasons[] = "用户不存在";
                        continue;
                    }

                    // 检查是否可以领取
                    $checkResult = $coupon->canUserReceive($userId);
                    if (!$checkResult['can_receive']) {
                        $failedUsers[] = $user->name;
                        $reasons[] = $checkResult['reason'];
                        continue;
                    }

                    // 为每个用户创建指定数量的优惠券
                    for ($i = 0; $i < $quantityPerUser; $i++) {

                        // 创建用户优惠券
                        UserCoupon::create([
                            'user_id' => $userId,
                            'coupon_id' => $coupon->id,
                            'code' => UserCoupon::generateUniqueCode(),
                            'status' => UserCoupon::STATUS_UNUSED,
                            'received_at' => Carbon::now(),
                            'expire_at' => $expireAt,
                        ]);

                        $distributedCount++;
                    }
                }

                // 更新分发记录
                $distribution->update(['distributed_quantity' => $distributedCount]);
            });

            // 构建详细的消息
            $message = "成功发放{$distributedCount}张优惠券";
            
            if (!empty($failedUsers)) {
                $message .= "\n\n以下用户无法领取：\n";
                for ($i = 0; $i < count($failedUsers); $i++) {
                    $message .= "• {$failedUsers[$i]}: {$reasons[$i]}\n";
                }
            }

            return [
                'success' => true,
                'message' => $message,
                'distributed_count' => $distributedCount
            ];
        } catch (\Exception $e) {
            Log::error('批量发放优惠券失败', [
                'coupon_id' => $couponId,
                'user_ids' => $userIds,
                'error' => $e->getMessage()
            ]);

            return ['success' => false, 'message' => '发放失败，请稍后重试', 'distributed_count' => 0];
        }
    }

    /**
     * 获取用户可用的优惠券
     *
     * @param int $userId
     * @param float $orderAmount
     * @param array $items
     * @return array
     */
    public function getAvailableCoupons(int $userId, float $orderAmount, array $items): array
    {
        // 获取用户所有未使用的优惠券
        $userCoupons = UserCoupon::with('coupon')
            ->where('user_id', $userId)
            ->unused()
            ->get();

        $availableCoupons = [];
        $unavailableCoupons = [];

        foreach ($userCoupons as $userCoupon) {
            $coupon = $userCoupon->coupon;

            // 计算优惠金额
            $result = $coupon->calculateDiscount($orderAmount, $items);

            $data = [
                'user_coupon_id' => $userCoupon->id,
                'coupon' => $coupon,
                'user_coupon' => $userCoupon,
                'discount' => $result['discount'],
                'reason' => $result['reason'],
            ];

            if ($result['can_use']) {
                $availableCoupons[] = $data;
            } else {
                $unavailableCoupons[] = $data;
            }
        }

        // 按优惠金额降序排序
        usort($availableCoupons, function ($a, $b) {
            return $b['discount'] <=> $a['discount'];
        });

        return [
            'available' => $availableCoupons,
            'unavailable' => $unavailableCoupons,
        ];
    }

    /**
     * 计算优惠金额
     *
     * @param int $userCouponId
     * @param float $orderAmount
     * @param array $items
     * @return array ['success' => bool, 'discount' => float, 'message' => string]
     */
    public function calculateDiscount(int $userCouponId, float $orderAmount, array $items): array
    {
        $userCoupon = UserCoupon::with('coupon')->find($userCouponId);

        if (!$userCoupon) {
            return ['success' => false, 'discount' => 0, 'message' => '优惠券不存在'];
        }

        if (!$userCoupon->is_available) {
            return ['success' => false, 'discount' => 0, 'message' => '优惠券不可用'];
        }

        $result = $userCoupon->coupon->calculateDiscount($orderAmount, $items);

        return [
            'success' => $result['can_use'],
            'discount' => $result['discount'],
            'message' => $result['reason']
        ];
    }

    /**
     * 使用优惠券
     *
     * @param int $userCouponId
     * @param int $orderId
     * @param float $discountAmount
     * @return bool
     */
    public function useCoupon(int $userCouponId, int $orderId, float $discountAmount): bool
    {
        try {
            $userCoupon = UserCoupon::find($userCouponId);

            if (!$userCoupon) {
                return false;
            }

            return $userCoupon->markAsUsed($orderId, $discountAmount);
        } catch (\Exception $e) {
            Log::error('使用优惠券失败', [
                'user_coupon_id' => $userCouponId,
                'order_id' => $orderId,
                'error' => $e->getMessage()
            ]);

            return false;
        }
    }

    /**
     * 退回优惠券（订单取消时）
     *
     * @param int $userCouponId
     * @return bool
     */
    public function refundCoupon(int $userCouponId): bool
    {
        try {
            $userCoupon = UserCoupon::find($userCouponId);

            if (!$userCoupon) {
                return false;
            }

            return $userCoupon->refund();
        } catch (\Exception $e) {
            Log::error('退回优惠券失败', [
                'user_coupon_id' => $userCouponId,
                'error' => $e->getMessage()
            ]);

            return false;
        }
    }

    /**
     * 过期用户优惠券（定时任务调用）
     *
     * @return int 过期的优惠券数量
     */
    public function expireUserCoupons(): int
    {
        try {
            // 查找所有应该过期的优惠券
            $expiredCount = UserCoupon::where('status', UserCoupon::STATUS_UNUSED)
                ->where('expire_at', '<=', Carbon::now())
                ->update(['status' => UserCoupon::STATUS_EXPIRED]);

            Log::info('优惠券过期任务执行完成', ['expired_count' => $expiredCount]);

            return $expiredCount;
        } catch (\Exception $e) {
            Log::error('优惠券过期任务失败', ['error' => $e->getMessage()]);
            return 0;
        }
    }

    /**
     * 检查用户领取资格
     *
     * @param int $userId
     * @param int $couponId
     * @return array ['can_receive' => bool, 'reason' => string]
     */
    public function checkCouponEligibility(int $userId, int $couponId): array
    {
        $coupon = Coupon::find($couponId);

        if (!$coupon) {
            return ['can_receive' => false, 'reason' => '优惠券不存在'];
        }

        return $coupon->canUserReceive($userId);
    }

    /**
     * 计算过期时间
     *
     * @param Coupon $coupon
     * @return Carbon
     */
    protected function calculateExpireTime(Coupon $coupon): Carbon
    {
        // 如果设置了固定结束时间，使用结束时间
        if ($coupon->end_time) {
            return $coupon->end_time;
        }

        // 如果设置了有效天数，从领取时间开始计算
        if ($coupon->valid_days) {
            return Carbon::now()->addDays($coupon->valid_days);
        }

        // 默认30天有效期
        return Carbon::now()->addDays(30);
    }

    /**
     * 获取用户的优惠券统计
     *
     * @param int $userId
     * @return array
     */
    public function getUserCouponStats(int $userId): array
    {
        return [
            'total' => UserCoupon::where('user_id', $userId)->count(),
            'unused' => UserCoupon::where('user_id', $userId)->unused()->count(),
            'used' => UserCoupon::where('user_id', $userId)->used()->count(),
            'expired' => UserCoupon::where('user_id', $userId)->expired()->count(),
            'expiring_soon' => UserCoupon::where('user_id', $userId)->expiringSoon()->count(),
        ];
    }
}

